Android14 VSync 机制深入解读
The following article is from 阿豪讲Framework Author 阿豪
如果你玩过 PC 上的大型游戏,应该知道游戏中通常有一个叫做垂直同步
的选项,如果不开这个选项,游戏过程中可能有画面撕裂的情况。
图片来自 https://sspai.com/post/63440
左侧是画面撕裂的情况,右侧是正常情况。
这种情况出现的主要原因是屏幕的刷新和主机的渲染不同步,假如,你是富哥,买了一张 4090 显卡,主机渲染图形非常快,但是你的显示器还是创业初期闲鱼捡的垃圾,刷新很慢(60hz),你游戏的时候,没有开垂直同步,当一帧还没全部刷新到屏幕上,下一帧数据又来了,显示器通常会中断当前帧的刷新,去刷新下一帧,这个时候,显示器上显示的就是当前帧和上一帧组合的图像,如果显示内容变化较大,你就能察觉到画面的撕裂。
这个问题最初是在 PC 上被重视和解决的,GPU 厂商开发出了一种防止屏幕被撕裂的技术方案,全称 Vertical Synchronization(中文名垂直同步,简称 VSync)。基本思路就是显示器在屏幕刷新之前向外提供一个信号,主机端根据此信号选择合适的策略完成画面的刷新,避免数据刷新和屏幕扫描不匹配(撕裂)的情况发生。
1VSync 基本框架
从硬件视角来看 VSync 其实就是一个电平信号,显示器的驱动板上有一个单独的引脚,这个引脚会根据显示器的刷新率定时的改变其高低电平。主机端需要有一个单独的 GPIO 与之相连,获取其信号变化;软件视角中的 VSync 其实就是一个 GPIO 的中断,一般是上升沿的中断。
当 Vsync 信号到来时,linux 内核就会收到一个中断,内核会根据对应的中断号去调用对应的中断处理函数。VSync 的中断处理函数会调用到 DRM 模块中,DRM 模块进一步又会调用到 HWComposor Hal 模块,HWComposor HAL 最终会回调到 SurfaceFlinger 中注册的 Vsync 硬件信号回调函数。
SurfaceFlinger 中的回调函数收到硬件传递来的 Vsync 信号后,会使用 VsyncSchedule 将 Vsync 信号到达时间和 Vsync 信号周期等信息记录下来并完成一些计算工作。当 App 需要绘制图像时, Choreographer 通过 Binder 向 VsyncSchedule 发起一个请求信号,VsyncSchedule 收到请求后会通过刚才记录的信息计算出软件 Vsync 信号,然后通过 socket 将该信号传递给 App,App 收到信号后开始绘制工作。
所以,我们并没有直接使用硬件 Vsync 信号,而是处理计算后的软件 Vsync 信号,在 Android14 中,软件 Vsync 信号有三类:
app-vsync:控制 app 上帧的 vsync,触发 app 进行绘制 appsf-vsync: 控制 app 上帧的 vsync,触发 app 进行绘制 和 app-vsync相位上有一定的偏差,使用较少 sf-vsync:控制 SurfaceFliner 进行合成的 vsync
那么这里就有一个问题,为什么 App 不直接使用硬件 Vsync 信号,要计算一个软件 Vsync 信号给 App 用?我觉得主要有以下几个原因:
直接使用硬件 Vsync 更费电,Vsync 是一个周期性的信号,容易通过软件定时器模拟。通过软件模拟,可以关闭硬件 Vsync,达到省电的目的。 让每个使用的 App 和 Surfacefliner 去直接监听硬件 vsync 会导致上层直接连接到硬件,这样的耦合性太高了,不利于软件的迭代。 App 获取硬件 Vsync 信号涉及到内核态与用户态的转换,周期性的信号会导致频繁的用户态内核态转换,造成较高的 cpu 资源占用。 软件 Vsync 信号之间合理的相位差,会使得图形的绘制与合成效率更高,这是单个硬件 Vsync 信号做不到的。
2Vsync 相关初始化
2.1 CompositionEngine 初始化
SurfaceFlinger 有一个重要成员 mCompositionEngine,CompositionEngine 充当了 SurfaceFlinger 与 RenderEngine(渲染引擎,主要用于图层 GPU 合成)和 HWComposer(硬件混合渲染器,主要用于图层硬件合成)之间的桥梁。
mCompositionEngine 在 SurfaceFlinger 的构造函数中初始化:
SurfaceFlinger::SurfaceFlinger(Factory& factory, SkipInitializationTag)
: mFactory(factory),
mPid(getpid()),
mTimeStats(std::make_shared<impl::TimeStats>()),
mFrameTracer(mFactory.createFrameTracer()),
mFrameTimeline(mFactory.createFrameTimeline(mTimeStats, mPid)),
// 关注点
mCompositionEngine(mFactory.createCompositionEngine()),
mHwcServiceName(base::GetProperty("debug.sf.hwc_service_name"s, "default"s)),
mTunnelModeEnabledReporter(sp<TunnelModeEnabledReporter>::make()),
mEmulatedDisplayDensity(getDensityFromProperty("qemu.sf.lcd_density", false)),
mInternalDisplayDensity(
getDensityFromProperty("ro.sf.lcd_density", !mEmulatedDisplayDensity)),
mPowerAdvisor(std::make_unique<Hwc2::impl::PowerAdvisor>(*this)),
mWindowInfosListenerInvoker(sp<WindowInfosListenerInvoker>::make()) {
ALOGI("Using HWComposer service: %s", mHwcServiceName.c_str());
}
mCompositionEngine 通过 mFactory.createCompositionEngine() 初始化,前面分析过 mFactory 的实际类型是 DefaultFactory。具体实现如下:
// /frameworks/native/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp
std::unique_ptr<compositionengine::CompositionEngine> DefaultFactory::createCompositionEngine() {
return compositionengine::impl::createCompositionEngine();
}
// /frameworks/native/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp
std::unique_ptr<compositionengine::CompositionEngine> createCompositionEngine() {
return std::make_unique<CompositionEngine>();
}
实际就是 new 了一个 CompositionEngine 对象,CompositionEngine 构造函数是默认实现,我们就不再看了。
2.2 RenderEngine 初始化
在 SurfaceFlinger 的启动过程中会执行到 SurfaceFlinger::init()
函数,在该函数中会初始化 Vsync 相关的对象。
// /frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::init() FTL_FAKE_GUARD(kMainThreadContext) {
// .....
// 关注点 1
// 构建 RenderEngine,用于 Client 合成
auto builder = renderengine::RenderEngineCreationArgs::Builder()
. 1`(static_cast<int32_t>(defaultCompositionPixelFormat))
.setImageCacheSize(maxFrameBufferAcquiredBuffers)
.setUseColorManagerment(useColorManagement)
.setEnableProtectedContext(enable_protected_contents(false))
.setPrecacheToneMapperShaderOnly(false)
.setSupportsBackgroundBlur(mSupportsBlur)
.setContextPriority(
useContextPriority
? renderengine::RenderEngine::ContextPriority::REALTIME
: renderengine::RenderEngine::ContextPriority::MEDIUM);
if (auto type = chooseRenderEngineTypeViaSysProp()) {
builder.setRenderEngineType(type.value());
}
mRenderEngine = renderengine::RenderEngine::create(builder.build());
mCompositionEngine->setRenderEngine(mRenderEngine.get());
// ......
// 关注点2
// 创建HWComposer对象并传入一个name属性,再通过mCompositionEngine->setHwComposer设置对象属性。
mCompositionEngine->setHwComposer(getFactory().createHWComposer(mHwcServiceName));
// 这里的this就是SurfaceFlinger对象本身,因为它实现了HWC2::ComposerCallback回调接口
mCompositionEngine->getHwComposer().setCallback(*this);
// ......
// Commit primary display.
sp<const DisplayDevice> display;
if (const auto indexOpt = mCurrentState.getDisplayIndex(getPrimaryDisplayIdLocked())) {
const auto& displays = mCurrentState.displays;
const auto& token = displays.keyAt(*indexOpt);
const auto& state = displays.valueAt(*indexOpt);
// 关注点3
processDisplayAdded(token, state);
mDrawingState.displays.add(token, state);
//
display = getDefaultDisplayDeviceLocked();
}
//......
// 关注点4
initScheduler(display);
// ......
}
关注点 1,初始化了一个 renderengine::RenderEngineCreationArgs::Builder
对象,接着将 builder 对象传入 create 函数构建一个 RenderEngine 对象,create 函数的实现如下:
std::unique_ptr<RenderEngine> RenderEngine::create(const RenderEngineCreationArgs& args) {
// 构建 builder 时,没有配置 renderEngineType 参数
// 使用默认值 RenderEngine::RenderEngineType::SKIA_GL_THREADED
switch (args.renderEngineType) {
case RenderEngineType::THREADED:
ALOGD("Threaded RenderEngine with GLES Backend");
return renderengine::threaded::RenderEngineThreaded::create(
[args]() { return android::renderengine::gl::GLESRenderEngine::create(args); },
args.renderEngineType);
case RenderEngineType::SKIA_GL:
ALOGD("RenderEngine with SkiaGL Backend");
return renderengine::skia::SkiaGLRenderEngine::create(args);
case RenderEngineType::SKIA_VK:
ALOGD("RenderEngine with SkiaVK Backend");
return renderengine::skia::SkiaVkRenderEngine::create(args);
case RenderEngineType::SKIA_GL_THREADED: { // 走这个分支
ALOGD("Threaded RenderEngine with SkiaGL Backend");
return renderengine::threaded::RenderEngineThreaded::create(
[args]() {
return android::renderengine::skia::SkiaGLRenderEngine::create(args);
},
args.renderEngineType);
}
case RenderEngineType::SKIA_VK_THREADED:
ALOGD("Threaded RenderEngine with SkiaVK Backend");
return renderengine::threaded::RenderEngineThreaded::create(
[args]() {
return android::renderengine::skia::SkiaVkRenderEngine::create(args);
},
args.renderEngineType);
case RenderEngineType::GLES:
default:
ALOGD("RenderEngine with GLES Backend");
return renderengine::gl::GLESRenderEngine::create(args);
}
}
create 函数会走到 SKIA_GL_THREADED 这个 case, create 一个 RenderEngineThreaded 对象返回:
std::unique_ptr<RenderEngineThreaded> RenderEngineThreaded::create(CreateInstanceFactory factory,
RenderEngineType type) {
return std::make_unique<RenderEngineThreaded>(std::move(factory), type);
}
实际就是 new 一个 RenderEngineThreaded,其构造函数如下:
RenderEngineThreaded::RenderEngineThreaded(CreateInstanceFactory factory, RenderEngineType type)
: RenderEngine(type) {
ATRACE_CALL();
std::lock_guard lockThread(mThreadMutex);
mThread = std::thread(&RenderEngineThreaded::threadMain, this, factory);
}
在构造函数中会启动一个线程,线程的主函数是 RenderEngineThreaded::threadMain:
void RenderEngineThreaded::threadMain(CreateInstanceFactory factory) NO_THREAD_SAFETY_ANALYSIS {
ATRACE_CALL();
if (!SetTaskProfiles(0, {"SFRenderEnginePolicy"})) {
ALOGW("Failed to set render-engine task profile!");
}
if (setSchedFifo(true) != NO_ERROR) {
ALOGW("Couldn't set SCHED_FIFO");
}
// SkiaGLRenderEngine 类型
mRenderEngine = factory();
pthread_setname_np(pthread_self(), mThreadName);
{
std::scoped_lock lock(mInitializedMutex);
mIsInitialized = true;
}
mInitializedCondition.notify_all();
while (mRunning) {
const auto getNextTask = [this]() -> std::optional<Work> {
std::scoped_lock lock(mThreadMutex);
if (!mFunctionCalls.empty()) {
Work task = mFunctionCalls.front();
mFunctionCalls.pop();
return std::make_optional<Work>(task);
}
return std::nullopt;
};
const auto task = getNextTask();
if (task) {
(*task)(*mRenderEngine);
}
std::unique_lock<std::mutex> lock(mThreadMutex);
mCondition.wait(lock, [this]() REQUIRES(mThreadMutex) {
return !mRunning || !mFunctionCalls.empty();
});
}
// we must release the RenderEngine on the thread that created it
mRenderEngine.reset();
}
完成基本的初始化,主要是使用传入的 factory(create 的时候传入的 lamda 表达式) 构建一个 SkiaGLRenderEngine 对象,然后进入一个无线循环,取 task,执行 task,然后 lock 到锁对象上,等待唤醒。
容易猜到,这里的 Task 应该就是图层的 GPU 合成工作。
最后会调用到 mCompositionEngine->setRenderEngine(mRenderEngine.get());
把构建好的 RenderEngine 对象给到 CompositionEngine 的 mRenderEngine 成员.
// /frameworks/native/services/surfaceflinger/ClientCache.h
void setRenderEngine(renderengine::RenderEngine* renderEngine) { mRenderEngine = renderEngine; }
相关类的关系如下图所示:
2.3 HWComposer 初始化
接着回到 init 函数中,我们来看看关注点 2 处:
// 关注点2
// 创建HWComposer对象并传入一个name属性,再通过mCompositionEngine->setHwComposer设置对象属性。
mCompositionEngine->setHwComposer(getFactory().createHWComposer(mHwcServiceName));
// 这里的this就是SurfaceFlinger对象本身,因为它实现了HWC2::ComposerCallback回调接口
mCompositionEngine->getHwComposer().setCallback(*this);
首先,明确一点,HardWare Composor hal 是以 Binder 服务的形式存在于系统中的,这里通过 DefaultFactory 构建一个 HwComposer 对象,根据我们以往的分析源码的经验,HwComposer 大概率是一个 Binder 代理端类的包装类。
接下来我们来分析 HwComposer 的初始化过程。
// /frameworks/native/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp
std::unique_ptr<HWComposer> DefaultFactory::createHWComposer(const std::string& serviceName) {
return std::make_unique<android::impl::HWComposer>(serviceName);
}
直接 new 一个 android::impl::HWComposer,其构造函数实现如下:
// /frameworks/native/services/surfaceflinger/DisplayHardware/HWComposer.cpp
HWComposer::HWComposer(const std::string& composerServiceName)
: HWComposer(Hwc2::Composer::create(composerServiceName)) {}
HWComposer::HWComposer(std::unique_ptr<Hwc2::Composer> composer)
: mComposer(std::move(composer)),
mMaxVirtualDisplayDimension(static_cast<size_t>(sysprop::max_virtual_display_dimension(0))),
mUpdateDeviceProductInfoOnHotplugReconnect(
sysprop::update_device_product_info_on_hotplug_reconnect(false)) {}
接着会调用 create 函数构造一个 AidlComposer 对象,然后调用另一个构造函数重载:
std::unique_ptr<Composer> Composer::create(const std::string& serviceName) {
if (AidlComposer::isDeclared(serviceName)) { // 新版本都会走该分支,使用 aidl hal
return std::make_unique<AidlComposer>(serviceName);
}
return std::make_unique<HidlComposer>(serviceName);
}
AidlComposer 是 IComposer 的包装类,IComposer 实际就是 HWComposer Hal Binder 服务的代理端对象,用于发起 Binder 远程过程调用。构造函数实现如下:
// /frameworks/native/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
std::shared_ptr<AidlIComposer> mAidlComposer;
std::shared_ptr<AidlIComposerClient> mAidlComposerClient;
// /frameworks/native/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
AidlComposer::AidlComposer(const std::string& serviceName) {
// This only waits if the service is actually declared
// 拿到代理端对象
mAidlComposer = AidlIComposer::fromBinder(
ndk::SpAIBinder(AServiceManager_waitForService(instance(serviceName).c_str())));
if (!mAidlComposer) {
LOG_ALWAYS_FATAL("Failed to get AIDL composer service");
return;
}
// 拿到匿名 Binder 服务的代理端对象 mAidlComposerClient
if (!mAidlComposer->createClient(&mAidlComposerClient).isOk()) {
LOG_ALWAYS_FATAL("Can't create AidlComposerClient, fallback to HIDL");
return;
}
addReader(translate<Display>(kSingleReaderKey));
// If unable to read interface version, then become backwards compatible.
int32_t version = 1;
const auto status = mAidlComposerClient->getInterfaceVersion(&version);
if (!status.isOk()) {
ALOGE("getInterfaceVersion for AidlComposer constructor failed %s",
status.getDescription().c_str());
}
mSupportsBufferSlotsToClear = version > 1;
if (!mSupportsBufferSlotsToClear) {
if (sysprop::clear_slots_with_set_layer_buffer(false)) {
mClearSlotBuffer = sp<GraphicBuffer>::make(1, 1, PIXEL_FORMAT_RGBX_8888,
GraphicBuffer::USAGE_HW_COMPOSER |
GraphicBuffer::USAGE_SW_READ_OFTEN |
GraphicBuffer::USAGE_SW_WRITE_OFTEN,
"AidlComposer");
if (!mClearSlotBuffer || mClearSlotBuffer->initCheck() != ::android::OK) {
LOG_ALWAYS_FATAL("Failed to allocate a buffer for clearing layer buffer slots");
return;
}
}
}
ALOGI("Loaded AIDL composer3 HAL service");
}
在构造函数中,首先通过 ServiceManager 获取到 HWComposer Hal 的代理端对象 mAidlComposer,接着通过 mAidlComposer 发起远程调用获取到匿名 Binder 服务的代理端对象 mAidlComposerClient。都是 Binder 的基本操作了。不在细说了。总而言之,AidlComposer 类包装了与 HWC Hal 交互的接口,让使用方更为方便地操作 HWC Hal。
到这里呢,我们就梳理出了 CompositionEngine 相关类的关系图:
总之,CompositionEngine 是 SurfaceFlinger 与 RenderEngine 和 HWComposer 沟通的桥梁,RenderEngine 负责图层的GPU 合成,HWComposer 负责图层的硬件合成。
2.4 HWComposer 回调注册
SurfaceFlinger::init 中接下来会给 HwComposer 注册一个回调对象:
// 这里的this就是SurfaceFlinger对象本身,因为它实现了HWC2::ComposerCallback回调接口
mCompositionEngine->getHwComposer().setCallback(*this);
给 HwComposor 对象注册了回调对象 this,也就是 SurfaceFlinger 对象,SurfaceFlinger 继承了 HWC2::ComposerCallback
接口,HWC2::ComposerCallback
中定义了 VSYNC信号、插拔显示器等的回调事件函数:
// /frameworks/native/services/surfaceflinger/DisplayHardware/HWC2.h
struct ComposerCallback {
// 显示器热插拔事件
virtual void onComposerHalHotplug(hal::HWDisplayId, hal::Connection) = 0;
// 显示器 refresh 刷新事件
virtual void onComposerHalRefresh(hal::HWDisplayId) = 0;
// VSYNC 信号事件
virtual void onComposerHalVsync(hal::HWDisplayId, nsecs_t timestamp,
std::optional<hal::VsyncPeriodNanos>) = 0;
//......
};
我们主要关心 onComposerHalVsync 函数,当硬件 Vsync 信号发生时,经过层层调用,最终会调用到这个函数,这部分会在后续的 Vsync 信号分发部分讲解。
2.5 DisplayDevice 初始化
SurfaceFlinger init 函数中的关注点 3,processDisplayAdded 会进行 Display 相关的初始化工作.
sp<const DisplayDevice> display;
if (const auto indexOpt = mCurrentState.getDisplayIndex(getPrimaryDisplayIdLocked())) {
// 返回类型为 DefaultKeyedVector<wp<IBinder>, DisplayDeviceState>
const auto& displays = mCurrentState.displays;
const auto& token = displays.keyAt(*indexOpt);
const auto& state = displays.valueAt(*indexOpt);
// 关注点3
processDisplayAdded(token, state);
mDrawingState.displays.add(token, state);
//
display = getDefaultDisplayDeviceLocked();
}
拿到主显示器的 index 这里从 mCurrentState 获取到 DefaultKeyedVector<wp<IBinder>, DisplayDeviceState>
,从 DefaultKeyedVector<wp<IBinder>, DisplayDeviceState>
中获取到显示器的 Token 和 DisplayDeviceState,然后传递给 processDisplayAdded 函数处理
processDisplayAdded 函数的实现如下:
// /frameworks/native/services/surfaceflinger/SurfaceFlinger.h
display::DisplayMap<wp<IBinder>, const sp<DisplayDevice>> mDisplays GUARDED_BY(mStateLock);
// /frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::processDisplayAdded(const wp<IBinder>& displayToken,
const DisplayDeviceState& state) {
// ......
auto display = setupNewDisplayDeviceInternal(displayToken, std::move(compositionDisplay), state,
displaySurface, producer);
// ....
mDisplays.try_emplace(displayToken, std::move(display));
}
processDisplayAdded 中会进一步调用 setupNewDisplayDeviceInternal 函数:
sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal(
const wp<IBinder>& displayToken,
std::shared_ptr<compositionengine::Display> compositionDisplay,
const DisplayDeviceState& state,
const sp<compositionengine::DisplaySurface>& displaySurface,
const sp<IGraphicBufferProducer>& producer) {
// ......
// creationArgs 用于构建 DisplayDevice 对象
creationArgs.refreshRateSelector =
mPhysicalDisplays.get(physical->id)
.transform(&PhysicalDisplay::snapshotRef)
.transform([&](const display::DisplaySnapshot& snapshot) {
// 构建了一个 RefreshRateSelector 对象
return std::make_shared<
scheduler::RefreshRateSelector>(snapshot.displayModes(),
creationArgs.activeModeId,
config);
})
.value_or(nullptr);
// .....
// 利用前面构建的 creationArgs 初始化一个 DisplayDevice 对象
// factory 就是 DefaultFactory
// 实际就是简单 new 一个 DisplayDevice
sp<DisplayDevice> display = getFactory().createDisplayDevice(creationArgs);
}
这里通过 creationArgs 中的参数来构建一个 DisplayDevice 对象,creationArgs 中的参数来自前面传入的 DisplayDeviceState对象,构建出的 DisplayDevice 对象代表了一个屏幕相关的配置信息。
creationArgs 中有一个成员 RefreshRateSelector。每个 DisplayDevice 对应一个 RefreshRateSelector 对象,该对象用于基于屏幕支持的刷新率范围,选择一个合适的 Refresh Rate 和 Frame Rate,并会传递给 VSyncSchedule 作为软件 VSync 生成的重要因素。
接着将 DisplayDevice 对象插入 mDisplays 中,后续会调用 getDefaultDisplayDeviceLocked 函数取出这个 DisplayDevice 对象。
2.6 initScheduler 函数实现分析
我们接着看 init 函数中的关注点 4, initScheduler 函数:
std::unique_ptr<scheduler::Scheduler> mScheduler;
scheduler::ConnectionHandle mAppConnectionHandle;
scheduler::ConnectionHandle mSfConnectionHandle;
// /frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
// 参数就是前面构建的 DisplayDevice 对象
void SurfaceFlinger::initScheduler(const sp<const DisplayDevice>& display) {
using namespace scheduler;
LOG_ALWAYS_FATAL_IF(mScheduler);
// 从前面构建的 RefreshRateSelector 获取 RefreshRate
// activeMode 就是当前屏幕的刷新率
const auto activeMode = display->refreshRateSelector().getActiveMode();
const Fps activeRefreshRate = activeMode.fps;
// new 一个 RefreshRateStats
mRefreshRateStats =
std::make_unique<RefreshRateStats>(*mTimeStats, activeRefreshRate, hal::PowerMode::OFF);
// 构建一个 VsyncConfiguration 对象
mVsyncConfiguration = getFactory().createVsyncConfiguration(activeRefreshRate);
// 配置 FeatureFlags
FeatureFlags features;
if (sysprop::use_content_detection_for_refresh_rate(false)) {
features |= Feature::kContentDetection;
}
if (base::GetBoolProperty("debug.sf.show_predicted_vsync"s, false)) {
features |= Feature::kTracePredictedVsync;
}
if (!base::GetBoolProperty("debug.sf.vsync_reactor_ignore_present_fences"s, false) &&
!getHwComposer().hasCapability(Capability::PRESENT_FENCE_IS_NOT_RELIABLE)) {
features |= Feature::kPresentFences;
}
if (display->refreshRateSelector().kernelIdleTimerController()) {
features |= Feature::kKernelIdleTimer;
}
// 构建一个 VsyncModulator 对象
// 根据事务调度和刷新率的变化调整 Vsync。
auto modulatorPtr = sp<VsyncModulator>::make(mVsyncConfiguration->getCurrentConfigs());
// 关注点1
// this + 前面构造的对象,初始化 Scheduler 对象
mScheduler = std::make_unique<Scheduler>(static_cast<ICompositor&>(*this),
static_cast<ISchedulerCallback&>(*this), features,
std::move(modulatorPtr));
// 关注点2
mScheduler->registerDisplay(display->getPhysicalId(), display->holdRefreshRateSelector());
// 关闭硬件 Vsync
setVsyncEnabled(display->getPhysicalId(), false);
// ?
mScheduler->startTimers();
const auto configs = mVsyncConfiguration->getCurrentConfigs();
// 关注点3
// 创建 VSYNC-app 对应的 EventThread
mAppConnectionHandle =
mScheduler->createEventThread(Scheduler::Cycle::Render,
mFrameTimeline->getTokenManager(),
/* workDuration */ configs.l ate.appWorkDuration,
/* readyDuration */ configs.late.sfWorkDuration);
// 创建 VSYNC-appSf 对应的 EventThread
mSfConnectionHandle =
mScheduler->createEventThread(Scheduler::Cycle::LastComposite,
mFrameTimeline->getTokenManager(),
/* workDuration */ activeRefreshRate.getPeriod(),
/* readyDuration */ configs.late.sfWorkDuration);
// 关注点4
// 创建 VSYNC-sf 对应的调度器
mScheduler->initVsync(mScheduler->getVsyncSchedule()->getDispatch(),
*mFrameTimeline->getTokenManager(), configs.late.sfWorkDuration);
mRegionSamplingThread =
sp<RegionSamplingThread>::make(*this,
RegionSamplingThread::EnvironmentTimingTunables());
mFpsReporter = sp<FpsReporter>::make(*mFrameTimeline, *this);
}
关注点 1,new 了一个 Scheduler 对象:
class Scheduler : android::impl::MessageQueue {
// ......
}
Scheduler 是生成和派发 VSync 的整体调度器,继承自 MessageQueue。构造函数实现如下:
// /frameworks/native/services/surfaceflinger/Scheduler/Scheduler.cpp
Scheduler::Scheduler(ICompositor& compositor, ISchedulerCallback& callback, FeatureFlags features,
sp<VsyncModulator> modulatorPtr)
: impl::MessageQueue(compositor),
mFeatures(features),
mVsyncModulator(std::move(modulatorPtr)),
mSchedulerCallback(callback) {}
// /frameworks/native/services/surfaceflinger/Scheduler/MessageQueue.cpp
MessageQueue::MessageQueue(ICompositor& compositor)
: MessageQueue(compositor, sp<Handler>::make(*this)) {}
MessageQueue::MessageQueue(ICompositor& compositor, sp<Handler> handler)
: mCompositor(compositor),
mLooper(sp<Looper>::make(kAllowNonCallbacks)),
mHandler(std::move(handler)) {}
Scheduler 的构造函数对内部的几个成员做了初始化:
mCompositor,传入的是 Surfaceflinger 对象 mFeatures,前面获取的一些 flags mVsyncModulator,根据事务调度和刷新率的变化调整 Vsync mSchedulerCallback,传入的是 Surfaceflinger 对象 mLooper mHandler:事件循环相关类
这些类的关系如下图所示:
关注点2 Scheduler::registerDisplay
Scheduler::registerDisplay 实现如下:
// /frameworks/native/services/surfaceflinger/Scheduler/Scheduler.cpp
void Scheduler::registerDisplay(PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr) {
registerDisplayInternal(displayId, std::move(selectorPtr),
// new 一个 VsyncSchedule 对象
std::make_shared<VsyncSchedule>(displayId, mFeatures));
}
先 new 一个 VsyncSchedule 对象,再调用 registerDisplayInternal 函数。
先看 new VsyncSchedule 的过程:
// /frameworks/native/services/surfaceflinger/Scheduler/VsyncSchedule.cpp
VsyncSchedule::VsyncSchedule(PhysicalDisplayId id, FeatureFlags features)
: mId(id),
mTracker(createTracker(id)),
mDispatch(createDispatch(mTracker)),
mController(createController(id, *mTracker, features)),
mTracer(features.test(Feature::kTracePredictedVsync)
? std::make_unique<PredictedVsyncTracer>(mDispatch)
: nullptr) {}
在构造函数中初始化了以下几个重要成员:
mTracker mDispatch mController
我们一个个看:
// /frameworks/native/services/surfaceflinger/Scheduler/VsyncSchedule.cpp
VsyncSchedule::TrackerPtr VsyncSchedule::createTracker(PhysicalDisplayId id) {
// TODO(b/144707443): Tune constants.
constexpr nsecs_t kInitialPeriod = (60_Hz).getPeriodNsecs();
constexpr size_t kHistorySize = 20;
constexpr size_t kMinSamplesForPrediction = 6;
constexpr uint32_t kDiscardOutlierPercent = 20;
return std::make_unique<VSyncPredictor>(id, kInitialPeriod, kHistorySize,
kMinSamplesForPrediction, kDiscardOutlierPercent);
}
就是 new 一个 VSyncPredictor 对象,VSyncPredictor 在 VsyncSchedule 的语境中为一个 Tracker,是负责综合各方因素根据算法由硬件 VSync 计算出软件 VSync 周期的工具类。
VSyncPredictor 的构造函数实现如下:
// /frameworks/native/services/surfaceflinger/Scheduler/VSyncPredictor.h
std::unordered_map<nsecs_t, Model> mutable mRateMap GUARDED_BY(mMutex);
// /frameworks/native/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
VSyncPredictor::VSyncPredictor(PhysicalDisplayId id, nsecs_t idealPeriod, size_t historySize,
size_t minimumSamplesForPrediction, uint32_t outlierTolerancePercent)
: mId(id),
mTraceOn(property_get_bool("debug.sf.vsp_trace", false)),
kHistorySize(historySize),
kMinimumSamplesForPrediction(minimumSamplesForPrediction),
kOutlierTolerancePercent(std::min(outlierTolerancePercent, kMaxPercent)),
mIdealPeriod(idealPeriod) {
resetModel();
}
void VSyncPredictor::resetModel() {
std::lock_guard lock(mMutex);
mRateMap[mIdealPeriod] = {mIdealPeriod, 0};
clearTimestamps();
}
构造函数中,初始化了很多参数值。这些参数都是用于后续计算软件 VSync 的。接着调用 resetModel(),给 mRateMap 插入一组初始化数据,mRateMap 是一个 unordered_map 类型的 数据,用于保存硬件 Vsync 相关的数据。
关于这些数据的作用以及软件 Vsync 的计算过程,会在本节后续相关章节详细讲解。
mDispatch 成员通过 createDispatch 初始化:
VsyncSchedule::DispatchPtr VsyncSchedule::createDispatch(TrackerPtr tracker) {
using namespace std::chrono_literals;
// TODO(b/144707443): Tune constants.
constexpr std::chrono::nanoseconds kGroupDispatchWithin = 500us;
constexpr std::chrono::nanoseconds kSnapToSameVsyncWithin = 3ms;
return std::make_unique<VSyncDispatchTimerQueue>(std::make_unique<Timer>(), std::move(tracker),
kGroupDispatchWithin.count(),
kSnapToSameVsyncWithin.count());
}
mDispatch 的实际类型是 VsyncDispatch,createDispatch 函数中会 new 一个 VSyncDispatchTimerQueue 对象(VsyncDispatch 的子类)并返回,该对象在 VsyncSchedule 的语境中为一个 Dispather,负责将 VSync 分发到使用者。
mController 成员通过 createController 函数初始化:
// /frameworks/native/services/surfaceflinger/Scheduler/VsyncSchedule.cpp
VsyncSchedule::ControllerPtr VsyncSchedule::createController(PhysicalDisplayId id,
VsyncTracker& tracker,
FeatureFlags features) {
// TODO(b/144707443): Tune constants.
constexpr size_t kMaxPendingFences = 20;
const bool hasKernelIdleTimer = features.test(Feature::kKernelIdleTimer);
auto reactor = std::make_unique<VSyncReactor>(id, std::make_unique<SystemClock>(), tracker,
kMaxPendingFences, hasKernelIdleTimer);
reactor->setIgnorePresentFences(!features.test(Feature::kPresentFences));
return reactor;
}
mController 的实际类型是 VsyncController。在 createController 函数中会 new 一个 VSyncReactor 对象(VsyncController 的子类)并返回。这个对象的主要作用是负责传递 HWVsync,presentFence 信号
到这里,VsyncSchedule 就初始化完成了,相关类的关系如下图所示:
接着看 registerDisplayInternal 的实现:
display::PhysicalDisplayMap<PhysicalDisplayId, Display> mDisplays
void Scheduler::registerDisplayInternal(PhysicalDisplayId displayId,
RefreshRateSelectorPtr selectorPtr,
VsyncSchedulePtr schedulePtr) {
demotePacesetterDisplay();
std::shared_ptr<VsyncSchedule> pacesetterVsyncSchedule;
{
std::scoped_lock lock(mDisplayLock);
// 把 display RefreshRateSelectorPtr VsyncSchedule 三个对象关联起来
mDisplays.emplace_or_replace(displayId, std::move(selectorPtr), std::move(schedulePtr));
// 应该就是刚才初始化的 VsyncSchedule 对象
pacesetterVsyncSchedule = promotePacesetterDisplayLocked();
}
applyNewVsyncSchedule(std::move(pacesetterVsyncSchedule));
}
把 display RefreshRateSelectorPtr VsyncSchedule 三个对象插入 mDisplays 成员中关联起来,实际后两个参数会构建一个 Display 对象再插入
接着调用 applyNewVsyncSchedule 函数:
void Scheduler::applyNewVsyncSchedule(std::shared_ptr<VsyncSchedule> vsyncSchedule) {
onNewVsyncSchedule(vsyncSchedule->getDispatch());
// mConnections 还是 empty 的,后续代码实际都不会执行
std::vector<android::EventThread*> threads;
{
std::lock_guard<std::mutex> lock(mConnectionsLock);
threads.reserve(mConnections.size());
for (auto& [_, connection] : mConnections) {
threads.push_back(connection.thread.get());
}
}
for (auto* thread : threads) {
thread->onNewVsyncSchedule(vsyncSchedule);
}
}
这里会接着调用 onNewVsyncSchedule 函数:
void MessageQueue::onNewVsyncSchedule(std::shared_ptr<scheduler::VSyncDispatch> dispatch) {
std::unique_ptr<scheduler::VSyncCallbackRegistration> oldRegistration;
{
std::lock_guard lock(mVsync.mutex);
oldRegistration = onNewVsyncScheduleLocked(std::move(dispatch));
}
// The old registration needs to be deleted after releasing mVsync.mutex to
// avoid deadlock. This is because the callback may be running on the timer
// thread. In that case, timerCallback sets
// VSyncDispatchTimerQueueEntry::mRunning to true, then attempts to lock
// mVsync.mutex. But if it's already locked, the VSyncCallbackRegistration's
// destructor has to wait until VSyncDispatchTimerQueueEntry::mRunning is
// set back to false, but it won't be until mVsync.mutex is released.
oldRegistration.reset();
}
接着调用 onNewVsyncScheduleLocked 函数:
struct Vsync {
frametimeline::TokenManager* tokenManager = nullptr;
mutable std::mutex mutex;
std::unique_ptr<scheduler::VSyncCallbackRegistration> registration GUARDED_BY(mutex);
TracedOrdinal<std::chrono::nanoseconds> workDuration
GUARDED_BY(mutex) = {"VsyncWorkDuration-sf", std::chrono::nanoseconds(0)};
TimePoint lastCallbackTime GUARDED_BY(mutex);
std::optional<nsecs_t> scheduledFrameTime GUARDED_BY(mutex);
TracedOrdinal<int> value = {"VSYNC-sf", 0};
};
Vsync mVsync;
std::unique_ptr<scheduler::VSyncCallbackRegistration> MessageQueue::onNewVsyncScheduleLocked(
std::shared_ptr<scheduler::VSyncDispatch> dispatch) {
// 这个时候 mVsync.registration 为空,reschedule 是 false
const bool reschedule = mVsync.registration &&
mVsync.registration->cancel() == scheduler::CancelResult::Cancelled;
auto oldRegistration = std::move(mVsync.registration);
// 关键点
mVsync.registration = std::make_unique<
scheduler::VSyncCallbackRegistration>(std::move(dispatch),
std::bind(&MessageQueue::vsyncCallback, this,
std::placeholders::_1,
std::placeholders::_2,
std::placeholders::_3),
"sf");
// 不进入
if (reschedule) {
mVsync.scheduledFrameTime =
mVsync.registration->schedule({.workDuration = mVsync.workDuration.get().count(),
.readyDuration = 0,
.earliestVsync = mVsync.lastCallbackTime.ns()});
}
return oldRegistration;
}
这里核心点就是 new 一个 VSyncCallbackRegistration 对象并保存在 mVsync 的 registration 成员中。
VSyncCallbackRegistration::VSyncCallbackRegistration(std::shared_ptr<VSyncDispatch> dispatch,
VSyncDispatch::Callback callback,
std::string callbackName)
: mDispatch(std::move(dispatch)),
mToken(mDispatch->registerCallback(std::move(callback), std::move(callbackName))) {}
VSyncCallbackRegistration 的构造函数中,会将 callback 注册到 mDispatch,这里的 callback 就是 MessageQueue::vsyncCallback。
VSyncDispatchTimerQueue::CallbackToken VSyncDispatchTimerQueue::registerCallback(
Callback callback, std::string callbackName) {
std::lock_guard lock(mMutex);
return CallbackToken{
mCallbacks
.emplace(++mCallbackToken,
std::make_shared<VSyncDispatchTimerQueueEntry>(std::move(callbackName),
std::move(callback),
mMinVsyncDistance))
.first->first};
}
这里把回调函数包装为 VSyncDispatchTimerQueueEntry 对象,并插入 mCallbacks 中。
后续会通过 VSyncCallbackRegistration 去申请 Vsync 信号,申请过程中会调用到这个回调函数来分发软件 Vsync 信号,这个我们会在本节后续章节详细分析。
到这里,我们 Scheduler 相关的类图就增加了两个类:
回到 SurfaceFlinger::initScheduler 的关注点3:
// 创建 VSYNC-app 对应的 EventThread
mAppConnectionHandle =
mScheduler->createEventThread(Scheduler::Cycle::Render,
mFrameTimeline->getTokenManager(),
/* workDuration */ configs.l ate.appWorkDuration,
/* readyDuration */ configs.late.sfWorkDuration);
// 创建 VSYNC-appSf 对应的 EventThread
mSfConnectionHandle =
mScheduler->createEventThread(Scheduler::Cycle::LastComposite,
mFrameTimeline->getTokenManager(),
/* workDuration */ activeRefreshRate.getPeriod(),
/* readyDuration */ configs.late.sfWorkDuration);
这里通过 createEventThread 函数构建了两个 EventThread 对象。
// /frameworks/native/services/surfaceflinger/Scheduler/Scheduler.cpp
ConnectionHandle Scheduler::createEventThread(Cycle cycle,
frametimeline::TokenManager* tokenManager,
std::chrono::nanoseconds workDuration,
std::chrono::nanoseconds readyDuration) {
auto eventThread = std::make_unique<impl::EventThread>(cycle == Cycle::Render ? "app" : "appSf",
getVsyncSchedule(), tokenManager,
makeThrottleVsyncCallback(),
makeGetVsyncPeriodFunction(),
workDuration, readyDuration);
auto& handle = cycle == Cycle::Render ? mAppConnectionHandle : mSfConnectionHandle;
handle = createConnection(std::move(eventThread));
return handle;
}
构建一个 EventThread 对象并创建对应的 Connection 对象,EventThread 是用处理 VSYNC 的一个独立线程。内部维护一个 while 无限循环。
一方面,通过 VSyncCallbackRegistration 去申请下一次 VSYNC, 另一方面,当 VSYNC 生成,通过 Connection 将 VSYNC 发送给 DisplayEventReceiver,也就是 VSYNC 的终端接收者。 一般情况下有两个 EventThread,一个是针对客户端应用侧的 VSYNC-app,另一个是客户端想使用 SF 同步信号的 VSYNC-appSf。
在初始化 SurfaceFlinger 时,创建了两个子线程(EventThread)用来分别向客户端派 app-vsync 事件和 appsf-vsync 事件,这两个 EventThread 最重要的区别是对应的 workduration,readyduration 不同。
workduration:代表自身工作的理论耗时 readyduration:代表自身工作完成后,传递给下一模块处理的等待时间
以 sf 和 app 举例:app 的 workduration 代表 app 绘制渲染一帧的理论耗时,app 的 readyduration 代表 app 绘制渲染一帧完成后交给 surfaceflinger 处理的理耗时,sf 的 workduration 代表 sf 处理这一帧的理论耗时,readyduration代表传递给下一模块处理的等待时间。
可见 app 的 readyduration== sf 的 workduration,且 sf 的 readyduration=0
接着看 EventThread 的构造函数:
// /frameworks/native/services/surfaceflinger/Scheduler/EventThread.h
State mState GUARDED_BY(mMutex) = State::Idle;
// /frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp
EventThread::EventThread(const char* name, std::shared_ptr<scheduler::VsyncSchedule> vsyncSchedule,
android::frametimeline::TokenManager* tokenManager,
ThrottleVsyncCallback throttleVsyncCallback,
GetVsyncPeriodFunction getVsyncPeriodFunction,
std::chrono::nanoseconds workDuration,
std::chrono::nanoseconds readyDuration)
: mThreadName(name),
mVsyncTracer(base::StringPrintf("VSYNC-%s", name), 0),
mWorkDuration(base::StringPrintf("VsyncWorkDuration-%s", name), workDuration),
mReadyDuration(readyDuration),
mVsyncSchedule(std::move(vsyncSchedule)),
mVsyncRegistration(mVsyncSchedule->getDispatch(), createDispatchCallback(), name),
mTokenManager(tokenManager),
mThrottleVsyncCallback(std::move(throttleVsyncCallback)),
mGetVsyncPeriodFunction(std::move(getVsyncPeriodFunction)) {
LOG_ALWAYS_FATAL_IF(getVsyncPeriodFunction == nullptr,
"getVsyncPeriodFunction must not be null");
// 构建一个线程对象
// 执行 threadMain 函数
mThread = std::thread([this]() NO_THREAD_SAFETY_ANALYSIS {
std::unique_lock<std::mutex> lock(mMutex);
threadMain(lock);
});
pthread_setname_np(mThread.native_handle(), mThreadName);
pid_t tid = pthread_gettid_np(mThread.native_handle());
// Use SCHED_FIFO to minimize jitter
constexpr int EVENT_THREAD_PRIORITY = 2;
struct sched_param param = {0};
param.sched_priority = EVENT_THREAD_PRIORITY;
if (pthread_setschedparam(mThread.native_handle(), SCHED_FIFO, ¶m) != 0) {
ALOGE("Couldn't set SCHED_FIFO for EventThread");
}
set_sched_policy(tid, SP_FOREGROUND);
}
EventThread::~EventThread() {
{
std::lock_guard<std::mutex> lock(mMutex);
mState = State::Quit;
mCondition.notify_all();
}
// 等待线程结束
mThread.join();
}
在 EventThread 的初始化过程中会,会启动一个线程,在该线程中会执行 EventThread::threaMain(),该函数是会执行一个 while 循环,该循环的运行受状态机控制:
// /frameworks/native/services/surfaceflinger/Scheduler/EventThread.h
enum class State {
Idle,
Quit,
SyntheticVSync,
VSync,
};
Idle:表示当前处于空闲状态,等待客户端注册或请求 Vsync 信号; Quit:退出循环,EventThread 被析构掉时。 SyntheticVSync:表示由 EventThread 来提供虚假的 Vsync 信号(灭屏、虚拟屏时会是这种状态,以 60Hz 的速度提供)。 VSync:表示正常亮屏时请求 Vsync 信号。
threaMain 的实现细节留在后续的 Vsync 信号分发章节来讲。
接着创建 Connection 对象:
// /frameworks/native/services/surfaceflinger/Scheduler/Scheduler.cpp
ConnectionHandle Scheduler::createConnection(std::unique_ptr<EventThread> eventThread) {
const ConnectionHandle handle = ConnectionHandle{mNextConnectionHandleId++};
ALOGV("Creating a connection handle with ID %" PRIuPTR, handle.id);
auto connection = createConnectionInternal(eventThread.get());
std::lock_guard<std::mutex> lock(mConnectionsLock);
mConnections.emplace(handle, Connection{connection, std::move(eventThread)});
return handle;
}
sp<EventThreadConnection> Scheduler::createConnectionInternal(
EventThread* eventThread, EventRegistrationFlags eventRegistration,
const sp<IBinder>& layerHandle) {
int32_t layerId = static_cast<int32_t>(LayerHandle::getLayerId(layerHandle));
auto connection = eventThread->createEventConnection([&] { resync(); }, eventRegistration);
mLayerHistory.attachChoreographer(layerId, connection);
return connection;
}
// /frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp
sp<EventThreadConnection> EventThread::createEventConnection(
ResyncCallback resyncCallback, EventRegistrationFlags eventRegistration) const {
return sp<EventThreadConnection>::make(const_cast<EventThread*>(this),
IPCThreadState::self()->getCallingUid(),
std::move(resyncCallback), eventRegistration);
}
其实就是 new 一个 EventThreadConnection 对象:
EventThreadConnection::EventThreadConnection(EventThread* eventThread, uid_t callingUid,
ResyncCallback resyncCallback,
EventRegistrationFlags eventRegistration)
: resyncCallback(std::move(resyncCallback)),
mOwnerUid(callingUid),
mEventRegistration(eventRegistration),
mEventThread(eventThread),
mChannel(gui::BitTube::DefaultSize) {}
mChannel 的类型是 BitTube ,包装了 socket ,用于与 app 通讯。
EventThreadConnection 中有几个重要的方法:
class EventThreadConnection : public gui::BnDisplayEventConnection {
public:
// 当vsync信号来临时,通过sockt-pair将信号发送给app
virtual status_t postEvent(const DisplayEventReceiver::Event& event);
// app通过binder跨进程调用此方法,将建立的socketpair返回给应用
binder::Status stealReceiveChannel(gui::BitTube* outChannel) override;
// binder跨进程方法跨进程调用此方法,将会向surfaceflinger请求一个vsync信号
binder::Status requestNextVsync() override; // asynchronous
VSyncRequest vsyncRequest = VSyncRequest::None;
// .....
}
app 会向 surfaceflinger binder 建立连接,该连接就是 EventThreadConnection,是一个匿名 Binder。连接建立后会把该连接保存在 EventThread 的 mDisplayEventConnections 列表中。如上文代码所展示 EventThreadConnection 继承自 BnDisplayEventConnection,故 EventThreadConnection 具有使用 binder 跨进程的能力,且是 binder 的服务端类。建立连接后,app 端会调用 stealReceiveChannel 方法将 socketpair 返回给 app,后续的 vsync 信号将会使用该 socketpair 不断分发给 app。
在 EventThreadConnection 中除了代码中注释的三个重要的方法外,还有一个变量 vsyncRequest ,类型为 VSyncRequest :
enum class VSyncRequest {
None = -2,
// Single wakes up for the next two frames to avoid scheduler overhead
Single = -1,
// SingleSuppressCallback only wakes up for the next frame
SingleSuppressCallback = 0,
Periodic = 1,
// Subsequent values are periods.
};
vsyncRequest 保存着对应 EventThreadConnection 申请 vsync 的状态
None:不请求 Single :该状态下会得到两次软件 vsync 回调 SingleSuppressCallback :该状态下会得到一次vsync回调 Periodic:亮屏下不使用该状态
需要注意的是 Single 状态下会收到两次 vsync 信号,能避免额外的唤醒循环。
Connection 用于与 DisplayEventReceiver 通信,发送 VSync 信号。
接着看关注点4
// 创建 VSYNC-sf 对应的调度器
mScheduler->initVsync(mScheduler->getVsyncSchedule()->getDispatch(),
*mFrameTimeline->getTokenManager(), configs.late.sfWorkDuration);
这里会初始化 VSYNC-sf 对应的调度器,initVsync 的实现如下:
void MessageQueue::initVsync(std::shared_ptr<scheduler::VSyncDispatch> dispatch,
frametimeline::TokenManager& tokenManager,
std::chrono::nanoseconds workDuration) {
std::unique_ptr<scheduler::VSyncCallbackRegistration> oldRegistration;
{
std::lock_guard lock(mVsync.mutex);
mVsync.workDuration = workDuration;
mVsync.tokenManager = &tokenManager;
oldRegistration = onNewVsyncScheduleLocked(std::move(dispatch));
}
// See comments in onNewVsyncSchedule. Today, oldRegistration should be
// empty, but nothing prevents us from calling initVsync multiple times, so
// go ahead and destruct it outside the lock for safety.
oldRegistration.reset();
}
这里会去执行 onNewVsyncScheduleLocked 函数,不过在前面的 registerDisplay 中已经执行过了,好像有点重复,我们就不在分析了。
分析到这里,相关类的类图如下图所示:
图片太大了,应该看不清,原图可以看:
https://boardmix.cn/app/share/CAE.CMLx1wwgASoQAwZm0kipbusPGafdxHYZ1zAGQAE/hxtUlY
3HwComposer 分发硬件 VSync 信号
在 surfaceflinger::init 中调用了 HwComposer 的 setCallback 方法,传入的参数是 surfaceflinger 对象。
mCompositionEngine->getHwComposer().setCallback(*this);
surfaceflinger 实现了 HWC2::ComposerCallback 回调接口。
HWC2::ComposerCallback
中定义了 VSYNC信号、插拔显示器等的回调事件函数:
// /frameworks/native/services/surfaceflinger/DisplayHardware/HWC2.h
struct ComposerCallback {
// 热插拔事件
virtual void onComposerHalHotplug(hal::HWDisplayId, hal::Connection) = 0;
// refresh 刷新事件
virtual void onComposerHalRefresh(hal::HWDisplayId) = 0;
// VSYNC 信号事件
virtual void onComposerHalVsync(hal::HWDisplayId, nsecs_t timestamp,
std::optional<hal::VsyncPeriodNanos>) = 0;
//......
};
当硬件 Vsync 信号(一般是上升沿)到来时,会回调到 SurfaceFlinger::onComposerHalVsync 函数。
// /android-14.0.0_r15/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::onComposerHalVsync(hal::HWDisplayId hwcDisplayId, int64_t timestamp,
std::optional<hal::VsyncPeriodNanos> vsyncPeriod) {
ATRACE_NAME(vsyncPeriod
? ftl::Concat(__func__, ' ', hwcDisplayId, ' ', *vsyncPeriod, "ns").c_str()
: ftl::Concat(__func__, ' ', hwcDisplayId).c_str());
Mutex::Autolock lock(mStateLock);
// 关注点1
if (const auto displayIdOpt = getHwComposer().onVsync(hwcDisplayId, timestamp)) {
// 关注点 2
if (mScheduler->addResyncSample(*displayIdOpt, timestamp, vsyncPeriod)) {
// 关注点 3
// period flushed
mScheduler->modulateVsync(displayIdOpt, &VsyncModulator::onRefreshRateChangeCompleted);
}
}
}
传入的三个参数:
hwcDisplayId 表示显示器的 ID,意思是当前的 Vysnc 信号来自哪个显示器 参数 timestamp 表示 Vsync 信号的时间点 vsyncPeriod 表示连续两个 Vsync 信号的时间间隔
关注点1 onVsync 的实现如下:
// /frameworks/native/services/surfaceflinger/DisplayHardware/HWComposer.cpp
// ID 类型转换外加一些特殊情况判断
std::optional<PhysicalDisplayId> HWComposer::onVsync(hal::HWDisplayId hwcDisplayId,
nsecs_t timestamp) {
const auto displayIdOpt = toPhysicalDisplayId(hwcDisplayId);
if (!displayIdOpt) {
LOG_HWC_DISPLAY_ERROR(hwcDisplayId, "Invalid HWC display");
return {};
}
RETURN_IF_INVALID_DISPLAY(*displayIdOpt, {});
auto& displayData = mDisplayData[*displayIdOpt];
{
// There have been reports of HWCs that signal several vsync events
// with the same timestamp when turning the display off and on. This
// is a bug in the HWC implementation, but filter the extra events
// out here so they don't cause havoc downstream.
if (timestamp == displayData.lastPresentTimestamp) {
ALOGW("Ignoring duplicate VSYNC event from HWC for display %s (t=%" PRId64 ")",
to_string(*displayIdOpt).c_str(), timestamp);
return {};
}
displayData.lastPresentTimestamp = timestamp;
}
ATRACE_INT(ftl::Concat("HW_VSYNC_", displayIdOpt->value).c_str(),
displayData.vsyncTraceToggle);
displayData.vsyncTraceToggle = !displayData.vsyncTraceToggle;
return displayIdOpt;
}
onVsync 中主要是 ID 类型的转换。
接着会调用 mScheduler->addResyncSample 添加的一个采样时间数据,这个采样数据经过一些算法处理后,会决定这个硬件的 vsync 是否需要上报到 app,以及是否需要打开和关闭硬件的 Vsync.
bool Scheduler::addResyncSample(PhysicalDisplayId id, nsecs_t timestamp,
std::optional<nsecs_t> hwcVsyncPeriodIn) {
// 转换一下格式
const auto hwcVsyncPeriod = ftl::Optional(hwcVsyncPeriodIn).transform([](nsecs_t nanos) {
return Period::fromNs(nanos);
});
// 拿到 VsyncSchedule 对象
auto schedule = getVsyncSchedule(id);
if (!schedule) {
ALOGW("%s: Invalid display %s!", __func__, to_string(id).c_str());
return false;
}
// 返回值表示硬件的 vsync 是否需要上报到 app
return schedule->addResyncSample(mSchedulerCallback, TimePoint::fromNs(timestamp),
hwcVsyncPeriod);
}
getVsyncSchedule 的实现如下:
auto Scheduler::getVsyncSchedule(std::optional<PhysicalDisplayId> idOpt) const
-> ConstVsyncSchedulePtr {
std::scoped_lock lock(mDisplayLock);
return getVsyncScheduleLocked(idOpt);
}
auto Scheduler::getVsyncScheduleLocked(std::optional<PhysicalDisplayId> idOpt) const
-> ConstVsyncSchedulePtr {
ftl::FakeGuard guard(kMainThreadContext);
if (!idOpt) {
LOG_ALWAYS_FATAL_IF(!mPacesetterDisplayId, "Missing a pacesetter!");
idOpt = mPacesetterDisplayId;
}
const auto displayOpt = mDisplays.get(*idOpt);
if (!displayOpt) {
return nullptr;
}
return displayOpt->get().schedulePtr;
}
就是从成员变量 mDisplays 中拿到 VsyncSchedule 对象。
接着调用 VsyncSchedule 的 addResyncSample 函数:
// 类型是 VsyncController 指针
const ControllerPtr mController;
// /frameworks/native/services/surfaceflinger/Scheduler/VsyncSchedule.cpp
bool VsyncSchedule::addResyncSample(ISchedulerCallback& callback, TimePoint timestamp,
ftl::Optional<Period> hwcVsyncPeriod) {
bool needsHwVsync = false;
bool periodFlushed = false;
{
std::lock_guard<std::mutex> lock(mHwVsyncLock);
if (mHwVsyncState == HwVsyncState::Enabled) {
needsHwVsync = mController->addHwVsyncTimestamp(timestamp.ns(),
hwcVsyncPeriod.transform(&Period::ns),
&periodFlushed);
}
}
if (needsHwVsync) {
enableHardwareVsync(callback);
} else {
disableHardwareVsync(callback, false /* disallow */);
}
return periodFlushed;
}
接着调用 mController->addHwVsyncTimestamp
mController 的实际类型是 VsyncController 指针,VsyncController 内部均为纯虚函数,是一个接口类,具体的实现类是 VSyncReactor。
VsyncReactor 用于将硬件 Vsync 信号转换为软件 Vsync 信号。一般需要两个输入,第一是硬件 Vsync 到达的时间点,第二就是 Vsync 信号的周期。
接着调用到 VSyncReactor 的 addHwVsyncTimestamp 函数记录着两个数据:
addHwVsyncTimestamp 函数给 VsyncReactor 的计算模型加一组数据
/*
* Adds a hw sync timestamp to the model. The controller will use the timestamp
* time as a vsync signal.
*
* \param [in] timestamp The HW Vsync timestamp
* \param [in] hwcVsyncPeriod The Vsync period reported by composer, if available
* \param [out] periodFlushed True if the vsync period changed is completed
* \return True if the model needs more vsync signals to make
* an accurate prediction,
* False otherwise
*/
bool VSyncReactor::addHwVsyncTimestamp(nsecs_t timestamp, std::optional<nsecs_t> hwcVsyncPeriod,
bool* periodFlushed) {
assert(periodFlushed);
std::lock_guard lock(mMutex);
if (periodConfirmed(timestamp, hwcVsyncPeriod)) {
ATRACE_FORMAT("VSR %" PRIu64 ": period confirmed", mId.value);
if (mPeriodTransitioningTo) {
mTracker.setPeriod(*mPeriodTransitioningTo);
*periodFlushed = true;
}
if (mLastHwVsync) {
mTracker.addVsyncTimestamp(*mLastHwVsync);
}
mTracker.addVsyncTimestamp(timestamp);
endPeriodTransition();
mMoreSamplesNeeded = mTracker.needsMoreSamples();
} else if (mPeriodConfirmationInProgress) {
ATRACE_FORMAT("VSR %" PRIu64 ": still confirming period", mId.value);
mLastHwVsync = timestamp;
mMoreSamplesNeeded = true;
*periodFlushed = false;
} else {
ATRACE_FORMAT("VSR %" PRIu64 ": adding sample", mId.value);
*periodFlushed = false;
mTracker.addVsyncTimestamp(timestamp);
mMoreSamplesNeeded = mTracker.needsMoreSamples();
}
if (!mMoreSamplesNeeded) {
setIgnorePresentFencesInternal(false);
}
return mMoreSamplesNeeded;
}
mTracker.setPeriod 添加周期
mTracker.addVsyncTimestamp 添加信号到达时间
实际就是根据参数去配置 mTracker,mTracker 的实际类型是 VSyncPredictor,是负责综合各方因素根据算法由硬件 VSync 计算出软件 VSync 周期的工具类。
接着调用 addVsyncTimestamp 向 VSyncPredictor 添加一组硬件 VSync 数据。
如果数据不少于 6 个,就会做计算
std::vector<nsecs_t> mTimestamps GUARDED_BY(mMutex);
bool VSyncPredictor::addVsyncTimestamp(nsecs_t timestamp) {
std::lock_guard lock(mMutex);
// ......
if (mTimestamps.size() != kHistorySize) {
mTimestamps.push_back(timestamp);
mLastTimestampIndex = next(mLastTimestampIndex);
} else {
mLastTimestampIndex = next(mLastTimestampIndex);
mTimestamps[mLastTimestampIndex] = timestamp;
}
traceInt64If("VSP-ts", timestamp);
// kMinimumSamplesForPrediction 的值为 6
// 少于 6 个数据,直接返回
// mIdealPeriod 是 16.6,也就是 60hz
const size_t numSamples = mTimestamps.size();
if (numSamples < kMinimumSamplesForPrediction) {
mRateMap[mIdealPeriod] = {mIdealPeriod, 0};
return true;
}
// 有六个数据后,往后走
// This is a 'simple linear regression' calculation of Y over X, with Y being the
// vsync timestamps, and X being the ordinal of vsync count.
// The calculated slope is the vsync period.
// Formula for reference:
// Sigma_i: means sum over all timestamps.
// mean(variable): statistical mean of variable.
// X: snapped ordinal of the timestamp
// Y: vsync timestamp
//
// Sigma_i( (X_i - mean(X)) * (Y_i - mean(Y) )
// slope = -------------------------------------------
// Sigma_i ( X_i - mean(X) ) ^ 2
//
// intercept = mean(Y) - slope * mean(X)
//
std::vector<nsecs_t> vsyncTS(numSamples); //搜集 Vsync 信号时间 y轴
std::vector<nsecs_t> ordinals(numSamples); // 搜集 Vsycn 信号顺序 x轴
// Normalizing to the oldest timestamp cuts down on error in calculating the intercept.
const auto oldestTS = *std::min_element(mTimestamps.begin(), mTimestamps.end());
auto it = mRateMap.find(mIdealPeriod);
auto const currentPeriod = it->second.slope; // 默认值是 16.6,也就是 60hz
// The mean of the ordinals must be precise for the intercept calculation, so scale them up for
// fixed-point arithmetic.
constexpr int64_t kScalingFactor = 1000; // 顺序值相比时间值太小了,做发大处理,发大的倍数就是 1000
nsecs_t meanTS = 0; // Vsync 信号时间平均值
nsecs_t meanOrdinal = 0; // Vsync 信号顺序平均值
for (size_t i = 0; i < numSamples; i++) {
// 时间使用相对值
const auto timestamp = mTimestamps[i] - oldestTS;
vsyncTS[i] = timestamp;
meanTS += timestamp;
// 计算顺序的方法
const auto ordinal = currentPeriod == 0
? 0
: (vsyncTS[i] + currentPeriod / 2) / currentPeriod * kScalingFactor;
ordinals[i] = ordinal;
meanOrdinal += ordinal;
}
// 计算出平均值
meanTS /= numSamples;
meanOrdinal /= numSamples;
for (size_t i = 0; i < numSamples; i++) {
vsyncTS[i] -= meanTS;
ordinals[i] -= meanOrdinal;
}
nsecs_t top = 0;
nsecs_t bottom = 0;
for (size_t i = 0; i < numSamples; i++) {
top += vsyncTS[i] * ordinals[i];
bottom += ordinals[i] * ordinals[i];
}
if (CC_UNLIKELY(bottom == 0)) { // 特殊情况处理
it->second = {mIdealPeriod, 0};
clearTimestamps();
return false;
}
nsecs_t const anticipatedPeriod = top * kScalingFactor / bottom; //截距
nsecs_t const intercept = meanTS - (anticipatedPeriod * meanOrdinal / kScalingFactor); // 斜率
auto const percent = std::abs(anticipatedPeriod - mIdealPeriod) * kMaxPercent / mIdealPeriod;
if (percent >= kOutlierTolerancePercent) {
it->second = {mIdealPeriod, 0};
clearTimestamps();
return false;
}
traceInt64If("VSP-period", anticipatedPeriod);
traceInt64If("VSP-intercept", intercept);
// 计算出的结果保存在 mRateMap 中
// anticipatedPeriod 就是 斜率
// intercept 就是截距
// 后续就可以根据这两个数据模拟出软件 VSync
it->second = {anticipatedPeriod, intercept}; // 数据记录到 mRateMap 中
ALOGV("model update ts %" PRIu64 ": %" PRId64 " slope: %" PRId64 " intercept: %" PRId64,
mId.value, timestamp, anticipatedPeriod, intercept);
return true;
}
函数的参数,也就是 Vsync 信号时间,会保存在 mTimestamps 中。
这里会根据硬件 Vysnc 计算出软件 Vysnc 的模型,使用的方法是 'simple linear regression',也就是简单线性回归。
工作几年后,我想大多数人都忘了,大一大二学习的数学知识了。这里我们就来回顾一下简单线性回归。
图片来自:https://www.bilibili.com/video/BV11Y4y1z7Ah/?spm_id_from=333.337.search-card.all.click&vd_source=dc959648d92fce190c8461996c134681
在当前的模型中,x 是 Vsync 信号的顺序值(1,2,3,4,5.....),y 是 Vsync 信号到来的时间。
通过简单线性回归的公式,就可以求出 y 与 x 之间的一元一次关系。
计算出的结果保存在 mRateMap 中,后续会根据这里的数据来模拟软件 Vysnc 信号。
// /frameworks/native/services/surfaceflinger/Scheduler/VSyncPredictor.h
// Map between ideal vsync period and the calculated model
std::unordered_map<nsecs_t, Model> mutable mRateMap GUARDED_BY(mMutex);
setPeriod 的实现:
void VSyncPredictor::setPeriod(nsecs_t period) {
ATRACE_FORMAT("%s %s", __func__, to_string(mId).c_str());
traceInt64("VSP-setPeriod", period);
std::lock_guard lock(mMutex);
static constexpr size_t kSizeLimit = 30;
if (CC_UNLIKELY(mRateMap.size() == kSizeLimit)) {
mRateMap.erase(mRateMap.begin());
}
mIdealPeriod = period;
if (mRateMap.find(period) == mRateMap.end()) {
mRateMap[mIdealPeriod] = {period, 0};
}
clearTimestamps();
}
也就是更新一下 mIdealPeriod 和 mRateMap 的值。
enableHardwareVsync 的实现如下:
void VsyncSchedule::enableHardwareVsync(ISchedulerCallback& callback) {
std::lock_guard<std::mutex> lock(mHwVsyncLock);
enableHardwareVsyncLocked(callback);
}
void VsyncSchedule::enableHardwareVsyncLocked(ISchedulerCallback& callback) {
if (mHwVsyncState == HwVsyncState::Disabled) {
getTracker().resetModel();
callback.setVsyncEnabled(mId, true);
mHwVsyncState = HwVsyncState::Enabled;
}
}
disableHardwareVsync 实现如下:
void VsyncSchedule::disableHardwareVsync(ISchedulerCallback& callback, bool disallow) {
std::lock_guard<std::mutex> lock(mHwVsyncLock);
switch (mHwVsyncState) {
case HwVsyncState::Enabled:
callback.setVsyncEnabled(mId, false);
[[fallthrough]];
case HwVsyncState::Disabled:
mHwVsyncState = disallow ? HwVsyncState::Disallowed : HwVsyncState::Disabled;
break;
case HwVsyncState::Disallowed:
break;
}
}
callback 就是前面传入的 mSchedulerCallback,该成员在 Scheduler 构造函数中初始化,实际类型是 SurfaceFlinger。
这里就会调用到 SurfaceFlinger 的 setVsyncEnabled 函数:
// /frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::setVsyncEnabled(PhysicalDisplayId id, bool enabled) {
const char* const whence = __func__;
ATRACE_FORMAT("%s (%d) for %" PRIu64, whence, enabled, id.value);
// On main thread to avoid race conditions with display power state.
// 这个应该是发一个消息给 Looper
static_cast<void>(mScheduler->schedule([=]() FTL_FAKE_GUARD(mStateLock) {
{
ftl::FakeGuard guard(kMainThreadContext);
if (auto schedule = mScheduler->getVsyncSchedule(id)) {
// 关注点2
schedule->setPendingHardwareVsyncState(enabled);
}
}
ATRACE_FORMAT("%s (%d) for %" PRIu64 " (main thread)", whence, enabled, id.value);
if (const auto display = getDisplayDeviceLocked(id); display && display->isPoweredOn()) {
// 关注点1
setHWCVsyncEnabled(id, enabled);
}
}));
}
关注点 1:
// /frameworks/native/services/surfaceflinger/Scheduler/VsyncSchedule.cpp
void setHWCVsyncEnabled(PhysicalDisplayId id, bool enabled) {
hal::Vsync halState = enabled ? hal::Vsync::ENABLE : hal::Vsync::DISABLE;
getHwComposer().setVsyncEnabled(id, halState);
}
关注点 2:
// /frameworks/native/services/surfaceflinger/Scheduler/VsyncSchedule.cpp
void VsyncSchedule::setPendingHardwareVsyncState(bool enabled) {
mPendingHwVsyncState = enabled ? HwVsyncState::Enabled : HwVsyncState::Disabled;
}
接着看 关注点3 modulateVsync 的实现:
// /frameworks/native/services/surfaceflinger/Scheduler/Scheduler.h
template <typename... Args,
typename Handler = std::optional<VsyncConfig> (VsyncModulator::*)(Args...)>
void modulateVsync(std::optional<PhysicalDisplayId> id, Handler handler, Args... args) {
if (id) {
std::scoped_lock lock(mDisplayLock);
ftl::FakeGuard guard(kMainThreadContext);
if (id != mPacesetterDisplayId) {
return;
}
}
// handler 回调获取到 config
if (const auto config = (*mVsyncModulator.*handler)(args...)) {
setVsyncConfig(*config, getPacesetterVsyncPeriod());
}
}
handler 回调获取到 config,handler 实际类型是 VsyncModulator::onRefreshRateChangeCompleted:
// /frameworks/native/services/surfaceflinger/Scheduler/VsyncModulator.cpp
VsyncModulator::VsyncConfigOpt VsyncModulator::onRefreshRateChangeCompleted() {
if (!mRefreshRateChangePending) return std::nullopt;
mRefreshRateChangePending = false;
return updateVsyncConfig();
}
VsyncConfig VsyncModulator::updateVsyncConfig() {
std::lock_guard<std::mutex> lock(mMutex);
return updateVsyncConfigLocked();
}
VsyncConfig VsyncModulator::updateVsyncConfigLocked() {
const VsyncConfig& offsets = getNextVsyncConfig();
mVsyncConfig = offsets;
if (mTraceDetailedInfo) {
const bool isEarly = &offsets == &mVsyncConfigSet.early;
const bool isEarlyGpu = &offsets == &mVsyncConfigSet.earlyGpu;
const bool isLate = &offsets == &mVsyncConfigSet.late;
ATRACE_INT("Vsync-EarlyOffsetsOn", isEarly);
ATRACE_INT("Vsync-EarlyGpuOffsetsOn", isEarlyGpu);
ATRACE_INT("Vsync-LateOffsetsOn", isLate);
}
return offsets;
}
const VsyncConfig& VsyncModulator::getNextVsyncConfig() const {
switch (getNextVsyncConfigType()) {
case VsyncConfigType::Early:
return mVsyncConfigSet.early;
case VsyncConfigType::EarlyGpu:
return mVsyncConfigSet.earlyGpu;
case VsyncConfigType::Late:
return mVsyncConfigSet.late;
}
}
auto VsyncModulator::getNextVsyncConfigType() const -> VsyncConfigType {
// Early offsets are used if we're in the middle of a refresh rate
// change, or if we recently begin a transaction.
if (!mEarlyWakeupRequests.empty() || mTransactionSchedule == Schedule::EarlyEnd ||
mEarlyTransactionFrames > 0 || mRefreshRateChangePending) {
return VsyncConfigType::Early;
} else if (mEarlyGpuFrames > 0) {
return VsyncConfigType::EarlyGpu;
} else {
return VsyncConfigType::Late;
}
}
接着调用 setVsyncConfig
:
// /frameworks/native/services/surfaceflinger/Scheduler/Scheduler.cpp
void Scheduler::setVsyncConfig(const VsyncConfig& config, Period vsyncPeriod) {
setDuration(mAppConnectionHandle,
/* workDuration */ config.appWorkDuration,
/* readyDuration */ config.sfWorkDuration);
setDuration(mSfConnectionHandle,
/* workDuration */ vsyncPeriod,
/* readyDuration */ config.sfWorkDuration);
setDuration(config.sfWorkDuration);
}
void Scheduler::setDuration(ConnectionHandle handle, std::chrono::nanoseconds workDuration,
std::chrono::nanoseconds readyDuration) {
android::EventThread* thread;
{
std::lock_guard<std::mutex> lock(mConnectionsLock);
RETURN_IF_INVALID_HANDLE(handle);
thread = mConnections[handle].thread.get();
}
thread->setDuration(workDuration, readyDuration);
}
void EventThread::setDuration(std::chrono::nanoseconds workDuration,
std::chrono::nanoseconds readyDuration) {
std::lock_guard<std::mutex> lock(mMutex);
mWorkDuration = workDuration;
mReadyDuration = readyDuration;
mVsyncRegistration.update({.workDuration = mWorkDuration.get().count(),
.readyDuration = mReadyDuration.count(),
.earliestVsync = mLastVsyncCallbackTime.ns()});
}
modulateVsync 实际就是给 EventThread 配置 workDuration readyDuration 参数。这些参数会用于计算 软件 Vsync 信号。
总结一下,收到硬件 Vsync 后,就是做一些计算和配置
4VSYNC-app 的请求流程
应用端通过 Choreographer 向 SurfaceFlinger 请求一个 app-Vsync,首先会建立匿名 Binder 连接 EventThreadConnection,EventThreadConnection 是一个 binder 服务端对象,所有的 EventThreadConnection 都会保存在 EventThread 的 mDisplayEventConnections 成员中。当 App 需要绘制时,就会调用到 EventThreadConnection::requestNextVsync() 申请一个 VSync-app 信号。
// /frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp
binder::Status EventThreadConnection::requestNextVsync() {
ATRACE_CALL();
mEventThread->requestNextVsync(sp<EventThreadConnection>::fromExisting(this));
return binder::Status::ok();
}
void EventThread::requestNextVsync(const sp<EventThreadConnection>& connection) {
if (connection->resyncCallback) {
connection->resyncCallback();
}
std::lock_guard<std::mutex> lock(mMutex);
// 第一次请求的时候 connection->vsyncRequest == VSyncRequest::None,进入如下逻辑,使得该连接的 vsyncRequest = VSyncRequest::Single
if (connection->vsyncRequest == VSyncRequest::None) {
connection->vsyncRequest = VSyncRequest::Single;
mCondition.notify_all();
} else if (connection->vsyncRequest == VSyncRequest::SingleSuppressCallback) {
connection->vsyncRequest = VSyncRequest::Single;
}
}
目前相关变量的情况如下:
mPendingEvents.isEmpty() = true mState = State::IDLE connection->vsyncRequest = VSyncRequest::Single
std::deque<DisplayEventReceiver::Event> mPendingEvents GUARDED_BY(mMutex);
void EventThread::threadMain(std::unique_lock<std::mutex>& lock) {
DisplayEventConsumers consumers;
while (mState != State::Quit) {
std::optional<DisplayEventReceiver::Event> event;
// 取 event
// mPendingEvents,存放着定时器唤醒后发给该EventThread的事件,
// Determine next event to dispatch.
if (!mPendingEvents.empty()) {
event = mPendingEvents.front();
mPendingEvents.pop_front();
if (event->header.type == DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG) {
if (event->hotplug.connected && !mVSyncState) {
mVSyncState.emplace(event->header.displayId);
} else if (!event->hotplug.connected && mVSyncState &&
mVSyncState->displayId == event->header.displayId) {
mVSyncState.reset();
}
}
}
bool vsyncRequested = false;
// 遍历所有连接
// 找到 consumer
// Find connections that should consume this event.
auto it = mDisplayEventConnections.begin();
while (it != mDisplayEventConnections.end()) {
if (const auto connection = it->promote()) {
if (event && shouldConsumeEvent(*event, connection)) {
consumers.push_back(connection);
}
vsyncRequested |= connection->vsyncRequest != VSyncRequest::None;
++it;
} else {
it = mDisplayEventConnections.erase(it);
}
}
// 分发 event 给 consumer
if (!consumers.empty()) {
dispatchEvent(*event, consumers);
consumers.clear();
}
if (mVSyncState && vsyncRequested) {
mState = mVSyncState->synthetic ? State::SyntheticVSync : State::VSync;
} else {
ALOGW_IF(!mVSyncState, "Ignoring VSYNC request while display is disconnected");
mState = State::Idle;
}
if (mState == State::VSync) {
// 请求 VSync 信号
// 实际就是向 mPendingEvents 添加 event
const auto scheduleResult =
mVsyncRegistration.schedule({.workDuration = mWorkDuration.get().count(),
.readyDuration = mReadyDuration.count(),
.earliestVsync = mLastVsyncCallbackTime.ns()});
LOG_ALWAYS_FATAL_IF(!scheduleResult, "Error scheduling callback");
} else {
mVsyncRegistration.cancel();
}
if (!mPendingEvents.empty()) {
continue;
}
// 等待 app 唤醒
// Wait for event or client registration/request.
if (mState == State::Idle) {
mCondition.wait(lock);
} else {
// Generate a fake VSYNC after a long timeout in case the driver stalls. When the
// display is off, keep feeding clients at 60 Hz.
const std::chrono::nanoseconds timeout =
mState == State::SyntheticVSync ? 16ms : 1000ms;
if (mCondition.wait_for(lock, timeout) == std::cv_status::timeout) {
if (mState == State::VSync) {
ALOGW("Faking VSYNC due to driver stall for thread %s", mThreadName);
}
LOG_FATAL_IF(!mVSyncState);
const auto now = systemTime(SYSTEM_TIME_MONOTONIC);
const auto deadlineTimestamp = now + timeout.count();
const auto expectedVSyncTime = deadlineTimestamp + timeout.count();
mPendingEvents.push_back(makeVSync(mVSyncState->displayId, now,
++mVSyncState->count, expectedVSyncTime,
deadlineTimestamp));
}
}
}
// cancel any pending vsync event before exiting
mVsyncRegistration.cancel();
}
调用 mVsyncRegistration.schedule
请求 VSync 信号。
// frameworks/native/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp
ScheduleResult VSyncCallbackRegistration::schedule(VSyncDispatch::ScheduleTiming scheduleTiming) {
if (!mToken) {
return std::nullopt;
}
return mDispatch->schedule(*mToken, scheduleTiming);
}
// /frameworks/native/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp
ScheduleResult VSyncDispatchTimerQueue::schedule(CallbackToken token,
ScheduleTiming scheduleTiming) {
std::lock_guard lock(mMutex);
return scheduleLocked(token, scheduleTiming);
}
ScheduleResult VSyncDispatchTimerQueue::scheduleLocked(CallbackToken token,
ScheduleTiming scheduleTiming) {
auto it = mCallbacks.find(token);
if (it == mCallbacks.end()) {
return {};
}
auto& callback = it->second;
auto const now = mTimeKeeper->now();
/* If the timer thread will run soon, we'll apply this work update via the callback
* timer recalculation to avoid cancelling a callback that is about to fire. */
auto const rearmImminent = now > mIntendedWakeupTime;
if (CC_UNLIKELY(rearmImminent)) {
callback->addPendingWorkloadUpdate(scheduleTiming);
return getExpectedCallbackTime(*mTracker, now, scheduleTiming);
}
// 关注点
const ScheduleResult result = callback->schedule(scheduleTiming, *mTracker, now);
if (!result.has_value()) {
return {};
}
if (callback->wakeupTime() < mIntendedWakeupTime - mTimerSlack) {
rearmTimerSkippingUpdateFor(now, it);
}
return result;
}
拿到回调对象 callback 然后调用 schedule。
callback 是什么时候初始化的呢?
在构建 EventThread 的时候,会初始化 mVsyncRegistration 成员。
// /frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp
EventThread::EventThread(const char* name, std::shared_ptr<scheduler::VsyncSchedule> vsyncSchedule,
android::frametimeline::TokenManager* tokenManager,
ThrottleVsyncCallback throttleVsyncCallback,
GetVsyncPeriodFunction getVsyncPeriodFunction,
std::chrono::nanoseconds workDuration,
std::chrono::nanoseconds readyDuration)
: mThreadName(name),
mVsyncTracer(base::StringPrintf("VSYNC-%s", name), 0),
mWorkDuration(base::StringPrintf("VsyncWorkDuration-%s", name), workDuration),
mReadyDuration(readyDuration),
mVsyncSchedule(std::move(vsyncSchedule)),
// 关注点 VSyncCallbackRegistration 初始化过程
mVsyncRegistration(mVsyncSchedule->getDispatch(), createDispatchCallback(), name),
mTokenManager(tokenManager),
mThrottleVsyncCallback(std::move(throttleVsyncCallback)),
mGetVsyncPeriodFunction(std::move(getVsyncPeriodFunction)) {
LOG_ALWAYS_FATAL_IF(getVsyncPeriodFunction == nullptr,
"getVsyncPeriodFunction must not be null");
// 构建一个线程对象
// 执行 threadMain 函数
mThread = std::thread([this]() NO_THREAD_SAFETY_ANALYSIS {
std::unique_lock<std::mutex> lock(mMutex);
threadMain(lock);
});
pthread_setname_np(mThread.native_handle(), mThreadName);
pid_t tid = pthread_gettid_np(mThread.native_handle());
// Use SCHED_FIFO to minimize jitter
constexpr int EVENT_THREAD_PRIORITY = 2;
struct sched_param param = {0};
param.sched_priority = EVENT_THREAD_PRIORITY;
if (pthread_setschedparam(mThread.native_handle(), SCHED_FIFO, ¶m) != 0) {
ALOGE("Couldn't set SCHED_FIFO for EventThread");
}
set_sched_policy(tid, SP_FOREGROUND);
}
这里会调用到 VsyncRegistration 的构造函数:
VSyncCallbackRegistration::VSyncCallbackRegistration(std::shared_ptr<VSyncDispatch> dispatch,
VSyncDispatch::Callback callback,
std::string callbackName)
: mDispatch(std::move(dispatch)),
mToken(mDispatch->registerCallback(std::move(callback), std::move(callbackName))) {}
// /frameworks/native/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp
VSyncDispatchTimerQueue::CallbackToken VSyncDispatchTimerQueue::registerCallback(
Callback callback, std::string callbackName) {
std::lock_guard lock(mMutex);
return CallbackToken{
mCallbacks
.emplace(++mCallbackToken,
std::make_shared<VSyncDispatchTimerQueueEntry>(std::move(callbackName),
std::move(callback),
mMinVsyncDistance))
.first->first};
}
这里把 callback 包装成 VSyncDispatchTimerQueueEntry,并添加到 mCallbacks 中。
callback 来自 createDispatchCallback 函数:
// /frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp
scheduler::VSyncDispatch::Callback EventThread::createDispatchCallback() {
// 直接返回一个 lamda
return [this](nsecs_t vsyncTime, nsecs_t wakeupTime, nsecs_t readyTime) {
onVsync(vsyncTime, wakeupTime, readyTime);
};
}
void EventThread::onVsync(nsecs_t vsyncTime, nsecs_t wakeupTime, nsecs_t readyTime) {
std::lock_guard<std::mutex> lock(mMutex);
mLastVsyncCallbackTime = TimePoint::fromNs(vsyncTime);
LOG_FATAL_IF(!mVSyncState);
mVsyncTracer = (mVsyncTracer + 1) % 2;
// 构建一个 Event 并插入 mPendingEvents
mPendingEvents.push_back(makeVSync(mVSyncState->displayId, wakeupTime, ++mVSyncState->count,
vsyncTime, readyTime));
mCondition.notify_all();
}
callback 的类型是 VSyncDispatchTimerQueueEntry,接着调用 callback 的 schedule 函数:
// /frameworks/native/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp
ScheduleResult VSyncDispatchTimerQueueEntry::schedule(VSyncDispatch::ScheduleTiming timing,
VSyncTracker& tracker, nsecs_t now) {
// 计算出 now + timing.workDuration + timing.readyDuration 时间点开始的下一次硬件 Vsync 信号
auto nextVsyncTime = tracker.nextAnticipatedVSyncTimeFrom(
std::max(timing.earliestVsync, now + timing.workDuration + timing.readyDuration));
// 计算出的软件 Vsync 时间点
auto nextWakeupTime = nextVsyncTime - timing.workDuration - timing.readyDuration;
bool const wouldSkipAVsyncTarget =
mArmedInfo && (nextVsyncTime > (mArmedInfo->mActualVsyncTime + mMinVsyncDistance));
bool const wouldSkipAWakeup =
mArmedInfo && ((nextWakeupTime > (mArmedInfo->mActualWakeupTime + mMinVsyncDistance)));
if (wouldSkipAVsyncTarget && wouldSkipAWakeup) {
return getExpectedCallbackTime(nextVsyncTime, timing);
}
nextVsyncTime = adjustVsyncIfNeeded(tracker, nextVsyncTime);
nextWakeupTime = nextVsyncTime - timing.workDuration - timing.readyDuration;
auto const nextReadyTime = nextVsyncTime - timing.readyDuration;
mScheduleTiming = timing;
mArmedInfo = {nextWakeupTime, nextVsyncTime, nextReadyTime};
return getExpectedCallbackTime(nextVsyncTime, timing);
}
这里就是计算下一次 VSync 的地方了。tracker 就是 VSyncPredictor,是计算 VSync 的核心类。
workduration 和 readyduration 在大多数情况下都是固定值,且对于 sync 计算来说是个固定值,是对于 app 和 sf 完成渲染和合成工作时间大概估计,vsync 时间点的计算和这两个值有关系。
如下图所示,是app-sync的时间点计算示意图:举例:app-sync:workduration:16.6ms readyduration: 15.6ms,那么 app-sync 的计算方式如下图所描述:
图片来自:https://blog.csdn.net/qq_41095045/article/details/136378829?spm=1001.2014.3001.5502
假如应用在24.9ms时向surfaceflinger申请app-vsync信号 在24.9ms基础上加上app-vsync的workduration和readyduration计算出时间点a 找出a的下一个HW_VSYNC的时间点:81ms 在a的的下一个HW_VSYNC的时间点上减去app-vsync的workduration和readyduration得到时间点b:48.8ms,改时间点就是未来app收到app-vsync的时间点 计算出surfaceflinger申请app-vsync信号的到时间点b的时间差:23.9ms,并设置定时 23.9m后app申请的app-vsync时间到,surfaceflinger向app发送app-vsync信号
以上演示的以 app-vsync 为例的 vsync 计算过程,appsf-vsync 和sf-vsync 的计算过程类似,不同的是appsf-vsync和sf-vsync的workduration,readyduration是不同的值,以使得信号之间保持一定的相位差。
在上面的 VSyncDispatchTimerQueue::scheduleLocked 中,schedule 计算完时间后,会调用 rearmTimerSkippingUpdateFor,而 rearmTimerSkippingUpdateFor 设置了一个 Alarm,定时执行 VSync 的回调:
void VSyncDispatchTimerQueue::rearmTimerSkippingUpdateFor(
nsecs_t now, CallbackMap::iterator const& skipUpdateIt) {
//...
setTimer(*min, now);
//...
}
void VSyncDispatchTimerQueue::setTimer(nsecs_t targetTime, nsecs_t /*now*/) {
mIntendedWakeupTime = targetTime;
// 定时回调 VSyncDispatchTimerQueue::timerCallback
mTimeKeeper->alarmAt(std::bind(&VSyncDispatchTimerQueue::timerCallback, this),
mIntendedWakeupTime);
mLastTimerSchedule = mTimeKeeper->now();
}
时间到了就会唤醒:
void VSyncDispatchTimerQueue::timerCallback() {
struct Invocation {
std::shared_ptr<VSyncDispatchTimerQueueEntry> callback;
nsecs_t vsyncTimestamp;
nsecs_t wakeupTimestamp;
nsecs_t deadlineTimestamp;
};
std::vector<Invocation> invocations;
{
std::lock_guard lock(mMutex);
auto const now = mTimeKeeper->now();
mLastTimerCallback = now;
for (auto it = mCallbacks.begin(); it != mCallbacks.end(); it++) {
// 遍历取出 callback
auto& callback = it->second;
auto const wakeupTime = callback->wakeupTime();
if (!wakeupTime) {
continue;
}
auto const readyTime = callback->readyTime();
auto const lagAllowance = std::max(now - mIntendedWakeupTime, static_cast<nsecs_t>(0));
if (*wakeupTime < mIntendedWakeupTime + mTimerSlack + lagAllowance) {
callback->executing();
// callback 包装到 Invocation 中
invocations.emplace_back(Invocation{callback, *callback->lastExecutedVsyncTarget(),
*wakeupTime, *readyTime});
}
}
mIntendedWakeupTime = kInvalidTime;
rearmTimer(mTimeKeeper->now());
}
for (auto const& invocation : invocations) {
// 回调
invocation.callback->callback(invocation.vsyncTimestamp, invocation.wakeupTimestamp,
invocation.deadlineTimestamp);
}
}
这里的 callback 来自 createDispatchCallback 函数:
scheduler::VSyncDispatch::Callback EventThread::createDispatchCallback() {
return [this](nsecs_t vsyncTime, nsecs_t wakeupTime, nsecs_t readyTime) {
onVsync(vsyncTime, wakeupTime, readyTime);
};
}
void EventThread::onVsync(nsecs_t vsyncTime, nsecs_t wakeupTime, nsecs_t readyTime) {
std::lock_guard<std::mutex> lock(mMutex);
mLastVsyncCallbackTime = TimePoint::fromNs(vsyncTime);
LOG_FATAL_IF(!mVSyncState);
mVsyncTracer = (mVsyncTracer + 1) % 2;
// 构建一个 event 添加到 mPendingEvents 中
mPendingEvents.push_back(makeVSync(mVSyncState->displayId, wakeupTime, ++mVSyncState->count,
vsyncTime, readyTime));
// 唤醒 EventThread
mCondition.notify_all();
}
// /frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp
DisplayEventReceiver::Event makeVSync(PhysicalDisplayId displayId, nsecs_t timestamp,
uint32_t count, nsecs_t expectedPresentationTime,
nsecs_t deadlineTimestamp) {
DisplayEventReceiver::Event event;
event.header = {DisplayEventReceiver::DISPLAY_EVENT_VSYNC, displayId, timestamp};
event.vsync.count = count;
event.vsync.vsyncData.preferredFrameTimelineIndex = 0;
// Temporarily store the current vsync information in frameTimelines[0], marked as
// platform-preferred. When the event is dispatched later, the frame interval at that time is
// used with this information to generate multiple frame timeline choices.
event.vsync.vsyncData.frameTimelines[0] = {.vsyncId = FrameTimelineInfo::INVALID_VSYNC_ID,
.deadlineTimestamp = deadlineTimestamp,
.expectedPresentationTime =
expectedPresentationTime};
return event;
}
Vsync 信号将会封装成 Event 放入 mPendingEvents,然后调用锁对象 mCondition 的 notify_all 通知其他wait 在这个锁对象的线程。
5VSYNC-app 的分发过程
EventThread 中的 threadmain 方法从 wait 中唤醒:
在之前的 threadMain 方法中,有代码:
if (!mPendingEvents.empty()) {
event = mPendingEvents.front();
mPendingEvents.pop_front();
if (event->header.type == DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG) {
if (event->hotplug.connected && !mVSyncState) {
mVSyncState.emplace(event->header.displayId);
} else if (!event->hotplug.connected && mVSyncState &&
mVSyncState->displayId == event->header.displayId) {
mVSyncState.reset();
}
}
}
...
if (!consumers.empty()) {
dispatchEvent(*event, consumers);
consumers.clear();
}
dispatchEvent 分发:
void EventThread::dispatchEvent(const DisplayEventReceiver::Event& event,
const DisplayEventConsumers& consumers) {
for (const auto& consumer : consumers) {
DisplayEventReceiver::Event copy = event;
if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
const int64_t frameInterval = mGetVsyncPeriodFunction(consumer->mOwnerUid);
copy.vsync.vsyncData.frameInterval = frameInterval;
generateFrameTimeline(copy.vsync.vsyncData, frameInterval, copy.header.timestamp,
event.vsync.vsyncData.preferredExpectedPresentationTime(),
event.vsync.vsyncData.preferredDeadlineTimestamp());
}
switch (consumer->postEvent(copy)) {
case NO_ERROR:
break;
case -EAGAIN:
// TODO: Try again if pipe is full.
ALOGW("Failed dispatching %s for %s", toString(event).c_str(),
toString(*consumer).c_str());
break;
default:
// Treat EPIPE and other errors as fatal.
removeDisplayEventConnectionLocked(consumer);
}
}
}
这里的 consumer 为 EventThreadConnection:
// /frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp
status_t EventThreadConnection::postEvent(const DisplayEventReceiver::Event& event) {
constexpr auto toStatus = [](ssize_t size) {
return size < 0 ? status_t(size) : status_t(NO_ERROR);
};
if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE ||
event.header.type == DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH) {
mPendingEvents.emplace_back(event);
if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE) {
return status_t(NO_ERROR);
}
auto size = DisplayEventReceiver::sendEvents(&mChannel, mPendingEvents.data(),
mPendingEvents.size());
mPendingEvents.clear();
return toStatus(size);
}
auto size = DisplayEventReceiver::sendEvents(&mChannel, &event, 1);
return toStatus(size);
}
DisplayEventReceiver::sendEvents 最终发给客户端:
ssize_t DisplayEventReceiver::sendEvents(gui::BitTube* dataChannel,
Event const* events, size_t count)
{
return gui::BitTube::sendObjects(dataChannel, events, count);
}
BitTube 通过 socket 将事件分发到客户端的 Choreographer。
6VSYNC-sf 的请求和分发
VSYNC-sf 初始化 MessageQueue::initVsync:
// /frameworks/native/services/surfaceflinger/Scheduler/MessageQueue.cpp
void MessageQueue::initVsync(std::shared_ptr<scheduler::VSyncDispatch> dispatch,
frametimeline::TokenManager& tokenManager,
std::chrono::nanoseconds workDuration) {
std::unique_ptr<scheduler::VSyncCallbackRegistration> oldRegistration;
{
std::lock_guard lock(mVsync.mutex);
mVsync.workDuration = workDuration;
mVsync.tokenManager = &tokenManager;
oldRegistration = onNewVsyncScheduleLocked(std::move(dispatch));
}
// See comments in onNewVsyncSchedule. Today, oldRegistration should be
// empty, but nothing prevents us from calling initVsync multiple times, so
// go ahead and destruct it outside the lock for safety.
oldRegistration.reset();
}
接着调用 onNewVsyncScheduleLocked 函数:
// /frameworks/native/services/surfaceflinger/Scheduler/MessageQueue.cpp
std::unique_ptr<scheduler::VSyncCallbackRegistration> MessageQueue::onNewVsyncScheduleLocked(
std::shared_ptr<scheduler::VSyncDispatch> dispatch) {
const bool reschedule = mVsync.registration &&
mVsync.registration->cancel() == scheduler::CancelResult::Cancelled;
auto oldRegistration = std::move(mVsync.registration);
mVsync.registration = std::make_unique<
scheduler::VSyncCallbackRegistration>(std::move(dispatch),
std::bind(&MessageQueue::vsyncCallback, this,
std::placeholders::_1,
std::placeholders::_2,
std::placeholders::_3),
"sf");
if (reschedule) {
mVsync.scheduledFrameTime =
mVsync.registration->schedule({.workDuration = mVsync.workDuration.get().count(),
.readyDuration = 0,
.earliestVsync = mVsync.lastCallbackTime.ns()});
}
return oldRegistration;
}
构建一个 VSyncCallbackRegistration 对象,VSyncCallbackRegistration 代表一个 VSync 使用者的注册。比如常见的针对上层应用的 VSYNC-app、针对 SurfaceFlinger 合成的VSYNC-sf,都对应一个 VSyncCallbackRegistration。另外在客户端,还有一个VSYNC-appSf。
当sf需要请求刷新时,会调用MessageQueue中的scheduleFrame函数
void MessageQueue::scheduleFrame() {
ATRACE_CALL();
std::lock_guard lock(mVsync.mutex);
mVsync.scheduledFrameTime =
mVsync.registration->schedule({.workDuration = mVsync.workDuration.get().count(),
.readyDuration = 0,
.earliestVsync = mVsync.lastCallbackTime.ns()});
}
计算过程都是和 app 一样的,最终的回调函数不一样,这里是 MessageQueue::vsyncCallback
// /frameworks/native/services/surfaceflinger/Scheduler/MessageQueue.cpp
void MessageQueue::vsyncCallback(nsecs_t vsyncTime, nsecs_t targetWakeupTime, nsecs_t readyTime) {
ATRACE_CALL();
// Trace VSYNC-sf
mVsync.value = (mVsync.value + 1) % 2;
const auto expectedVsyncTime = TimePoint::fromNs(vsyncTime);
{
std::lock_guard lock(mVsync.mutex);
mVsync.lastCallbackTime = expectedVsyncTime;
mVsync.scheduledFrameTime.reset();
}
const auto vsyncId = VsyncId{mVsync.tokenManager->generateTokenForPredictions(
{targetWakeupTime, readyTime, vsyncTime})};
mHandler->dispatchFrame(vsyncId, expectedVsyncTime);
}
MessageQueue本身是一个消息队列的实现类。这里看到收到VSync回调后,通过mHandler->dispatchFrame抛到队列里去了。最终会执行
// /frameworks/native/services/surfaceflinger/Scheduler/MessageQueue.cpp
void MessageQueue::Handler::handleMessage(const Message&) {
mFramePending.store(false);
mQueue.onFrameSignal(mQueue.mCompositor, mVsyncId, mExpectedVsyncTime);
}
// /frameworks/native/services/surfaceflinger/Scheduler/Scheduler.cpp
void Scheduler::onFrameSignal(ICompositor& compositor, VsyncId vsyncId,
TimePoint expectedVsyncTime) {
// ...
if (!compositor.commit(pacesetterId, targets)) return;
// ...
const auto resultsPerDisplay = compositor.composite(pacesetterId, targeters);
}
这里的 compositor 是 SurfaceFlinger。接下来就是由 SF 进行合成工作了即执行 commit 和 composite 两个函数。
参考资料
一文搞定Android VSync机制来龙去脉Android 13 VSYNC重学习Andoid SurfaceFlinger(二) VSYNC的开始,连续,结束Andoid SurfaceFlinger(三) VSYNC的申请,生产,下发与校准Android 14 - 绘制体系 - 概览Android 14 - 绘制体系 - VSync(1)Android-View绘制原理(03)-Vsync原理之App篇Android-View绘制原理(02)-VSync原理之SurfaceFlinger篇一文带你看懂Vsync Phase最后推荐一下我做的网站,玩Android: wanandroid.com ,包含详尽的知识体系、好用的工具,还有本公众号文章合集,欢迎体验和收藏!
扫一扫 关注我的公众号
如果你想要跟大家分享你的文章,欢迎投稿~
┏(^0^)┛明天见!